package util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

/**
 * Created by neo on 17-6-1.
 */
public class Dates {
  public static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat(
      "yyyy-MM-dd");
  public static final SimpleDateFormat MOUTH_FORMATTER = new SimpleDateFormat(
      "yyyy-MM");
  public static final SimpleDateFormat DATETIME_FORMATTER = new SimpleDateFormat(
      "yyyy-MM-dd HH:mm:ss");

  public static Date fromDate(String str) {
    Date result = null;

    try {
      result = DATE_FORMATTER.parse(str);
    } catch (Exception e) {
      // [Neo] Empty
    }

    return result;
  }

  public static Date fromDateMouth(String str) {
    Date result = null;

    try {
      result = MOUTH_FORMATTER.parse(str);
    } catch (Exception e) {
      // [Neo] Empty
    }

    return result;
  }

  public static Date fromDatetime(String str) {
    Date result = null;

    try {
      result = DATETIME_FORMATTER.parse(str);
    } catch (Exception e) {
      // [Neo] Empty
    }

    return result;
  }

  public static List<Date> getEveryDate(String from, String to) {
    List<Date> lDate = new ArrayList<Date>();
    lDate.add(Dates.fromDatetime(from));
    Calendar calBegin = Calendar.getInstance();
    // 使用给定的 Date 设置此 Calendar 的时间
    calBegin.setTime(Dates.fromDatetime(from));
    Calendar calEnd = Calendar.getInstance();
    // 使用给定的 Date 设置此 Calendar 的时间
    calEnd.setTime(Dates.fromDatetime(to));
    // 测试此日期是否在指定日期之后
    while (Dates.fromDatetime(to).after(calBegin.getTime())) {
      // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
      calBegin.add(Calendar.DAY_OF_MONTH, 1);
      lDate.add(calBegin.getTime());
    }
    return lDate;
  }

  public static int countWorkDay(int year, int month) {
    Calendar c = Calendar.getInstance();
    c.set(Calendar.YEAR, year);
    // 月份是从0开始计算，所以需要减1
    c.set(Calendar.MONTH, month - 1);

    // 当月最后一天的日期
    int max = c.getActualMaximum(Calendar.DAY_OF_MONTH);
    // 开始日期为1号
    int start = 1;
    // 计数
    int count = 0;
    while (start <= max) {
      c.set(Calendar.DAY_OF_MONTH, start);
      if (isWorkDay(c)) {
        count++;
      }
      start++;
    }
    return count;
  }

  // 判断是否工作日（未排除法定节假日，由于涉及到农历节日，处理很麻烦）
  public static boolean isWorkDay(Calendar c) {
    // 获取星期,1~7,其中1代表星期日，2代表星期一 ... 7代表星期六
    int week = c.get(Calendar.DAY_OF_WEEK);
    // 不是周六和周日的都认为是工作日
    return week != Calendar.SUNDAY && week != Calendar.SATURDAY;
  }

  public static String format(Date date, SimpleDateFormat format) {
    String result = null;

    try {
      result = format.format(date);
    } catch (Exception e) {
      // [Neo] Empty
    }

    return result;
  }

  public static String format(Date date, String pattern) {
    return format(date, new SimpleDateFormat(pattern));
  }

  public static String formatDate(Date date) {
    return format(date, DATE_FORMATTER);
  }

  public static String formatDateTime(Date date) {
    return format(date, DATETIME_FORMATTER);
  }

  public static String formatNow(String pattern) {
    return format(new Date(), new SimpleDateFormat(pattern));
  }

  public static String formatNowDate() {
    return format(new Date(), DATE_FORMATTER);
  }

  public static String formatNowDateTime(String pattern) {
    return format(new Date(), DATETIME_FORMATTER);
  }

  public static Date now() {
    return new Date();
  }

  public static Date getDate(DateRange type) {
    Calendar cal = Calendar.getInstance();

    switch (type) {
      case kThisYear:
        cal.set(Calendar.DAY_OF_YEAR, 1);
        break;

      case kThisYearEnd:
        cal.set(Calendar.DAY_OF_YEAR, 1);
        cal.add(Calendar.YEAR, 1);
        break;

      case kThisQuarter:
        int currentMonth = cal.get(Calendar.MONTH) + 1;

        if (currentMonth >= 1 && currentMonth <= 3) {
          cal.set(Calendar.MONTH, 0);
        } else if (currentMonth >= 4 && currentMonth <= 6) {
          cal.set(Calendar.MONTH, 3);
        } else if (currentMonth >= 7 && currentMonth <= 9) {
          cal.set(Calendar.MONTH, 6);
        } else if (currentMonth >= 10 && currentMonth <= 12) {
          cal.set(Calendar.MONTH, 9);
        }

        cal.set(Calendar.DATE, 1);
        break;

      case kThisMonth:
        cal.set(Calendar.DAY_OF_MONTH, 1);
        break;

      case kThisMonthEnd:
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.add(Calendar.MONTH, 1);
        break;

      case kThisWeekEnd:
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        cal.add(Calendar.DATE, 7);
        break;

      case kThisWeek:
      default:
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        break;
    }

    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    return cal.getTime();
  }

  public static String dateCalculation(Date date, String type, int step) {

    Calendar calendar = new GregorianCalendar();
    calendar.setTime(date);

    switch (type) {
      case "hour":
        calendar.add(calendar.HOUR, step);//把日期往后增加一小时.整数往后推,负数往前移动
        break;
      case "day":
        calendar.add(calendar.DATE, step);//把日期往后增加一天.整数往后推,负数往前移动
        break;
      case "week":
        calendar.add(calendar.WEEK_OF_YEAR, step);//把日期往后增加一周.整数往后推,负数往前移动
        break;
      case "month":
        calendar.add(calendar.MONTH, step);//把日期往后增加一个月.整数往后推,负数往前移动
        break;
      case "year":
        calendar.add(calendar.YEAR, step);//把日期往后增加一年.整数往后推,负数往前移动
        break;

      default:
        calendar.add(calendar.DATE, step);
        break;
    }
//    calendar.add(calendar.YEAR, 1);
//    calendar.add(calendar.WEEK_OF_MONTH, 1);//把日期往后增加一个月.整数往后推,负数往前移动
    return Dates.formatDate(calendar.getTime());
  }

  public static String getFirstOrLastOfWeek(String dateStr, String type) {
    Calendar cal = Calendar.getInstance();
    String result = "";
    try {
      cal.setTime(DATE_FORMATTER.parse(dateStr));

      int d = 0;
      if (cal.get(Calendar.DAY_OF_WEEK) == 1) {
        d = -6;
      } else {
        d = 2 - cal.get(Calendar.DAY_OF_WEEK);
      }
      cal.add(Calendar.DAY_OF_WEEK, d);
      if ("first".equals(type)) {
        // 所在周开始日期
        result = DATE_FORMATTER.format(cal.getTime());
      } else {
        cal.add(Calendar.DAY_OF_WEEK, 6);
        // 所在周结束日期
        result = DATE_FORMATTER.format(cal.getTime());
      }

    } catch (ParseException e) {

      e.printStackTrace();
    }

    return result;

  }

  public static List<Date> calLeaveDays(Date startTime, Date endTime) {
    List<Date> result = new ArrayList<Date>();

    //从startTime开始循环，若该日期不是节假日或者不是周六日则请假天数+1
    Date flag = startTime;//设置循环开始日期
    Calendar cal = Calendar.getInstance();
    while (flag.compareTo(endTime) != 1) {
      cal.setTime(flag);
      //判断是否为周六日
      int week = cal.get(Calendar.DAY_OF_WEEK) - 1;
      if (week == 0 || week == 6) {//0为周日，6为周六
        //跳出循环进入下一个日期
        cal.add(Calendar.DAY_OF_MONTH, +1);
        flag = cal.getTime();

        continue;
      }
      //不是节假日或者周末，天数+1
      result.add(flag);
      //日期往后加一天
      cal.add(Calendar.DAY_OF_MONTH, +1);
      flag = cal.getTime();
    }
    return result;
  }

  public static long timeDifference(Date startTime, Date endTime) {

    long diff = endTime.getTime() - startTime.getTime();//这样得到的差值是微秒级别
//    long days = diff / (1000 * 60 * 60 * 24);
//
//    long hours = (diff - days * (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
//    long minutes =
//        (diff - days * (1000 * 60 * 60 * 24) - hours * (1000 * 60 * 60)) / (1000
//            * 60);
//    Log.i("" + days + "天" + hours + "小时" + minutes + "分");
    long minutes = diff / (1000 * 60);

    return minutes;
  }

  public enum DateRange {
    kThisWeek,
    kThisWeekEnd,
    kThisMonth,
    kThisMonthEnd,
    kThisQuarter,
    kThisYear,
    kThisYearEnd
  }

}

